home *** CD-ROM | disk | FTP | other *** search
-
- /* Functions for optimizing a binary tree. A tree is optimized with a simple
- call to function "optimize(root)".
- */
-
- #include <stdio.h> /* Included only for compiler definition of NULL */
-
- /* Flag values */
- #define LEFT 1 /* Depth count/fold/"special" to the left */
- #define RIGHT 0 /* Depth count/fold/"special" to the right */
-
- /* Tree struct */
- typedef struct tnode { /* Standard binary tree node for storage */
- struct tnode *left, *right;
- /* Data would go here, but not needed. */
- } TREENODE;
-
- static
- TREENODE *worstroot, /* Pointer to worst-case root */
- *temp_root; /* Traversal pointer */
-
-
- /* Function prototypes */
- void *optimize(void *); /* Optimize a tree */
-
- static
- TREENODE *fixbranch(TREENODE *, int), /* "Fix" a branch */
- *fold(TREENODE *, int), /* "Fold" a branch */
- *special(TREENODE *, int); /* Perform "special" optimization */
-
- static
- int depth(TREENODE *, int); /* Determine depth of a branch */
-
- static
- void worstcase(TREENODE *); /* Rebuild tree into worst-case */
-
- /* Function to initiate the process of optimizing the tree. Optimization is
- performed by rearranging a binary tree into its worst-case form and then
- folding this new tree and any subtrees in half at any branch of a linear
- length of 3 or more nodes.
- Usage: void *optimize(opt_root)
- void *opt_root; /* Root of a binary tree
- Returns: A pointer to the optimized tree.
- */
- void *optimize(opt_root)
- void *opt_root;
- {
- int rdepth, ldepth; /* Depth of left & right subtrees */
- TREENODE *root; /* Pointer to working root of tree */
-
- if (opt_root == NULL)
- return(NULL);
-
- worstroot = temp_root = NULL;
- /* Build worst-case tree. Root is in "worstroot" */
- worstcase(opt_root);
- root = worstroot;
-
- /* Fold worst-case tree in half if three or more nodes */
- if (depth(root, RIGHT) > 1)
- root = fold(root, RIGHT);
-
- /* Fold left and right subtrees if three or more nodes */
- rdepth = depth(root, RIGHT);
- ldepth = depth(root, LEFT);
- if ((rdepth == 2) && (ldepth == 2))
- root = special(root, RIGHT);
- else
- if ((rdepth > 2) || (ldepth > 2)) {
- root = fixbranch(root, RIGHT);
- root = fixbranch(root, LEFT);
- }
- return((void *) root);
- }
-
-
- /* Function to determine the right or left depth of a local root NOT INCLUDING
- the local root itself.
- Usage: int depth(node, dir)
- TREENODE *node; /* Pointer to a local root
- int dir; /* Direction (LEFT or RIGHT)
- Returns: The depth of the local root.
- */
- int depth(node, dir)
- TREENODE *node;
- int dir;
- {
- int d = 0; /* Depth count */
- switch(dir) {
- case RIGHT:
- while (node->right != NULL) {
- d++;
- node = node->right;
- }
- break;
- case LEFT:
- while (node->left != NULL) {
- d++;
- node = node->left;
- }
- break;
- default:
- return(0);
- }
- return(d);
- }
-
-
- /* Function to handle a special optimization case at a local root.
-
- 3 4 2
- / \ / \ / \
- 2 4 changed to 2 5 or 1 4
- / \ / \ / \
- 1 5 1 3 3 5
- Case 1 Case 2
- This allows the section of the tree to remain in optimal form in the event
- a number is added that is greater than 5 in the first case, or less than 1
- in the second case.
- Usage: TREENODE *special(node, dir)
- TREENODE *node; /* Pointer to a local root
- int dir; /* Direction to hang the majority of nodes
- Returns: A pointer to the updated local root
- */
- TREENODE *special(node, dir)
- TREENODE *node;
- int dir;
- {
- TREENODE *temp, /* Temporary pointer */
- *newnode; /* Pointer to "specially" optimized subtree */
- switch(dir) {
- case RIGHT:
- node->left->right = node;
- temp = node->left;
- newnode = node->right;
- node->left = NULL;
- node->right = NULL;
- newnode->left = temp;
- break;
- case LEFT:
- node->right->left = node;
- temp = node->right;
- newnode = node->left;
- node->right = NULL;
- node->left = NULL;
- newnode->right = temp;
- break;
- default:
- newnode = node;
- break;
- }
- return(newnode);
- }
-
-
- /* Recursive function to initiate the folding of a worst-case local root
- into its most optimal form.
- Usage: TREENODE *fixbranch(node, dir)
- TREENODE *node; /* Pointer to a local root
- int dir; /* Direction to fix (LEFT or RIGHT)
- Returns: A pointer to an updated local root
- */
- TREENODE *fixbranch(node, dir)
- TREENODE *node;
- int dir;
- {
- switch(dir) {
-
- case RIGHT:
- /* Check for special case */
- if ((depth(node, RIGHT) == 2) && (depth(node, LEFT) == 2))
- node = special(node, dir);
- else
- /* Fold right subtree */
- node->right = fold(node->right, RIGHT);
- /* Fold new right subtree if three or more nodes including the root */
- if (depth(node->right, RIGHT) > 1)
- node->right = fixbranch(node->right, RIGHT);
- /* Fold new left subtree if four or more nodes including the root */
- if (depth(node->right, LEFT) > 2)
- node->right = fixbranch(node->right, LEFT);
- break;
-
- case LEFT:
- /* Check for special case */
- if ((depth(node, LEFT) == 2) && (depth(node, RIGHT) == 2))
- node = special(node, dir);
- else
- /* Fold left subtree */
- node->left = fold(node->left, LEFT);
- /* Fold new left subtree if three or more nodes including the root */
- if (depth(node->left, LEFT) > 1)
- node->left = fixbranch(node->left, LEFT);
- /* fold new right subtree if four or more nodes including the root */
- if (depth(node->left, RIGHT) > 2)
- node->left = fixbranch(node->left, RIGHT);
- break;
- }
- return(node);
- }
-
-
- /* Function to fold a branch of a local root in the direction given.
- Usage: TREENODE *fold(node, dir)
- TREENODE *node; /* Pointer to a local root
- int dir; /* Direction to fold
- Returns: A pointer to an updated local root
- */
- TREENODE *fold(node, dir)
- TREENODE *node;
- int dir;
- {
- TREENODE *newroot, /* Pointer to folded branch */
- *temproot; /* Temporary pointer */
- int ndepth, /* Node depth */
- loop; /* Looping variable */
- switch(dir) {
- case RIGHT:
- ndepth = depth(node, RIGHT);
- if (ndepth % 2)
- ndepth++; /* Leave any overhang to the left */
- ndepth >>= 1;
- /* Current parent node becomes left child for all nodes from the first
- node in the branch to the middle node */
- for (loop = 0; loop < ndepth; loop++) {
- node->right->left = node;
- temproot = node->right;
- node->right = NULL;
- node = temproot;
- }
- break;
-
- case LEFT:
- ndepth = depth(node, LEFT);
- if (ndepth % 2)
- ndepth++; /* Leave any overhang to the left */
- ndepth >>= 1;
- /* Current parent node becomes right child for all nodes from the first
- node in the branch to the middle node */
- for (loop = 0; loop < ndepth; loop++) {
- node->left->right = node;
- temproot = node->left;
- node->left = NULL;
- node = temproot;
- }
- break;
- default:
- return(NULL);
- break;
- }
- return(node);
- }
-
-
- /* Recursive fuction to rebuild a tree into its worst-case form. The root of
- the worst-case tree is stored in the global variable "worstroot".
- Usage: void worstcase(root)
- TREENODE *root; /* Pointer to root of a tree
- Returns: Nothing
- */
- void worstcase(root)
- TREENODE *root;
- {
- if (root != NULL) {
- worstcase(root->left);
- if (worstroot == NULL)
- temp_root = worstroot = root;
- else
- temp_root->right = root;
- root->left = NULL;
- temp_root = root;
- worstcase(root->right);
- }
- }
-